﻿// MIT License (MIT)
// Copyright (c) 2012 Sivakumar G
   
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
// and associated documentation files (the "Software"), to deal in the Software without restriction, 
// including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 
// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 
// subject to the following conditions:
   
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
   
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Xml.Linq;
using Sg.Silverlight.Utilities.SpellChecker.Api;

namespace Sg.Silverlight.Utilities.SpellChecker
{
  /// <summary>
  /// Spell check provider based on Google spell API
  /// </summary>
  public sealed class GoogleSpellCheckProvider : ISpellCheckProvider
  {
    #region Fields
    WebClient _webClient;
    const string _spellApiUri = "https://www.google.com/tbproxy/spell?lang=en";
    
    #endregion
    
    #region Ctor
    public GoogleSpellCheckProvider()
    {
      _webClient = new WebClient();
      _webClient.Headers["Content-Type"] = "application/x-www-form-urlencoded";
      _webClient.UploadStringCompleted += _webClient_UploadStringCompleted;
    }
    
    #endregion

    #region Events
    public event Action<SpellCheckResponse> SpellCheckCompleted;
    
    #endregion
    
    #region Methods
    public void DoSpellCheck(SpellCheckRequest request)
    {
      _webClient.UploadStringAsync(new Uri(_spellApiUri), "POST", BuildRequestXml(request).ToString(SaveOptions.None));
    }

    private XElement BuildRequestXml(SpellCheckRequest request)
    {
      var xElement = new XElement("spellrequest");
      xElement.SetAttributeValue("textalreadyclipped", request.TextClipped.ToBinaryString());
      xElement.SetAttributeValue("ignoramus", request.IgnoreDuplicates.ToBinaryString());
      xElement.SetAttributeValue("ignoredigits", request.IgnoreDigits.ToBinaryString());
      xElement.SetAttributeValue("ignoreallcaps", request.IgnoreAllCaps.ToBinaryString());
      xElement.Add(new XElement("text", string.Join(" ", request.Terms)));
      return xElement;
    }
    
    #endregion

    #region Event handlers
    void _webClient_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
    {
      var response = new SpellCheckResponse();
      if (null == e.Error && null != e.Result)
      {
        var xmlResponse = XElement.Parse(e.Result);
        var error = xmlResponse.Attribute("error").To<string>();
        if (error == "0")
        {
          foreach (var suggestion in xmlResponse.Elements())
          {
            response.Results.Add(new SpellCheckResponse.SpellCheckResult()
            {
              OffSet = suggestion.Attribute("o").To<int>(),
              Length = suggestion.Attribute("l").To<int>(),
              Confidence = suggestion.Attribute("s").To<string>(),
              Suggestions = suggestion.Value.Split('\t')
            });
          }
          if (null != SpellCheckCompleted)
          {
            SpellCheckCompleted(response);
          }
        }
        else
        {
          response.ErrorCode = error;
          if (null != SpellCheckCompleted)
          {
            SpellCheckCompleted(response);
          }
        }
      }
      else
      {
        response.ErrorCode = "Error reading spell check results from Google";
        if (null != SpellCheckCompleted)
        {
          SpellCheckCompleted(response);
        }
      }
    }
    #endregion
  }
}
